﻿using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Windows;
using Blackbird.Core.Editable.Base;
using Blackbird.Studio.Mvvm;
using Blackbird.Studio.ViewModel.Framework;

namespace Blackbird.Studio.ViewModel.EntityViewModels
{
    public abstract class EntityViewModel<T> : WorkspaceViewModel, IEntityViewModel where T : IEditableEntity
    {
        private Visibility _nodeDisplayVisibility = Visibility.Visible;
        private Visibility _nodeEditorVisibility = Visibility.Collapsed;
        private ObservableCollection<EntityCommandViewModel> _registeredCommands;

        protected EntityViewModel(T model)
        {
            Model = model;
            Model.PropertyChanged += ModelPropertyChanged;
        }

        public T Model { get; private set; }
        
        public virtual void Initialize()
        {
            Model.Initialize();
            CreateCommands();
            AddChildCommandVisibility = Visibility.Hidden;            
        }


        public Visibility AddChildCommandVisibility { get; protected set; }
        public RelayCommand DeleteCommand { get; set; }

        #region IEntityViewModel Members

        public IEntityCollectionViewModel ParentViewModel { get; set; }

        public ObservableCollection<EntityCommandViewModel> RegisteredCommands
        {
            get { return GetCommands(); }
        }

        public IEditableEntity Entity
        {
            get { return Model; }
        }

        public override string DisplayName
        {
            get { return Model.Name; }
            set
            {
                if (Model.Name != value)
                {
                    Model.Name = value;
                    InvokePropertyChanged("DisplayName");
                }
            }
        }

        public Visibility NodeEditorVisibility
        {
            get { return _nodeEditorVisibility; }
            set
            {
                if (_nodeEditorVisibility != value)
                {
                    _nodeEditorVisibility = value;
                    InvokePropertyChanged("NodeEditorVisibility");
                }
            }
        }

        public Visibility NodeDisplayVisibility
        {
            get { return _nodeDisplayVisibility; }
            set
            {
                if (_nodeDisplayVisibility != value)
                {
                    _nodeDisplayVisibility = value;
                    InvokePropertyChanged("NodeDisplayVisibility");
                }
            }
        }

        public RelayCommand BeginRenameCommand { get; private set; }
        public RelayCommand EndRenameCommand { get; private set; }

        public bool IsDirty
        {
            get { return Model.IsDirty; }
        }

        public abstract EntityType EntityType { get; }

        #endregion

        private void Delete(object param)
        {
            ParentViewModel.RemoveChildCommand.Command.Execute(this);
        }

        private void BeginRename(object param)
        {
            NodeDisplayVisibility = Visibility.Hidden;
            NodeEditorVisibility = Visibility.Visible;
        }

        private void EndRename(object param)
        {
            NodeDisplayVisibility = Visibility.Visible;
            NodeEditorVisibility = Visibility.Hidden;
        }

        internal virtual void CreateCommands()
        {
            BeginRenameCommand = new RelayCommand(BeginRename);
            EndRenameCommand = new RelayCommand(EndRename);
            DeleteCommand = new RelayCommand(Delete);
        }

        protected void RegisterCommand(EntityCommandViewModel command)
        {
            RegisteredCommands.Add(command);
        }

        protected virtual ObservableCollection<EntityCommandViewModel> GetCommands()
        {
            return _registeredCommands ?? (_registeredCommands = new ObservableCollection<EntityCommandViewModel>());
        }

        private void ModelPropertyChanged(object sender, PropertyChangedEventArgs e) {
            if(e.PropertyName == "Name")
            {
                if(NodeEditorVisibility == Visibility.Visible)
                {
                    EndRename(null);
                }
            }

            if(e.PropertyName == "IsSelected")
            {
                IsSelected = Model.IsSelected;
            }
        }

    }
}